package com.xy.util;

import org.im4java.core.ConvertCmd;
import org.im4java.core.IM4JavaException;
import org.im4java.core.IMOperation;
import org.im4java.core.IdentifyCmd;
import org.im4java.process.ArrayListOutputConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;

/**
 * Created by XiuYang on 2016/11/21.
 */
public class ImageOperateUtil {

    private static boolean isWindows = false;
    private static String magickPath = null;
    private static Logger logger = LoggerFactory.getLogger(ImageOperateUtil.class);

    static {
        String os = System.getenv("OS");
        if ("Windows_NT".equals(os)) {
            isWindows = true;
            magickPath = "D:\\Program Files\\ImageMagick-6.9.3-Q16";
        }
    }

    private static ConvertCmd getConvertCmd() {
        ConvertCmd convert = new ConvertCmd();
        if (isWindows) {
            convert.setSearchPath(magickPath);
        }

        return convert;
    }
    private static IdentifyCmd getIdentifyCmd() {
        IdentifyCmd convert = new IdentifyCmd();
        if (isWindows) {
            convert.setSearchPath(magickPath);
        }

        return convert;
    }

    /**
     * 切图
     *
     * @param source
     * @param dest
     * @param x
     * @param y
     * @param width
     * @param height
     * @throws IM4JavaException
     * @throws InterruptedException
     * @throws IOException
     */
    public static void cut(String source, String dest, int x, int y, int width, int height) throws IOException, InterruptedException, IM4JavaException {
        IMOperation op = new IMOperation();
        op.addImage(source);
        op.crop(width, height, x, y);
        op.addImage(dest);
        getConvertCmd().run(op, new Object[0]);
    }

    /**
     * 缩放
     *
     * @param source
     * @param dest
     * @param width
     * @param height
     * @throws IOException
     * @throws InterruptedException
     * @throws IM4JavaException
     */
    public static void zoom(String source, String dest, int width, int height) throws IOException, InterruptedException, IM4JavaException {
        if (width == 0 || height == 0) {
            logger.error("width and height cannot be 0 !");
            return;
        }

        IMOperation op = new IMOperation();
        op.addImage(source);
        op.resize(width, height);
        op.addImage(dest);
        getConvertCmd().run(op);
    }

    /**
     * 旋转
     *
     * @param source
     * @param dest
     * @param angle
     * @throws IOException
     * @throws InterruptedException
     * @throws IM4JavaException
     */
    public static void rotate(String source, String dest, double angle) throws IOException, InterruptedException, IM4JavaException {
        IMOperation op = new IMOperation();
        op.rotate(angle);
        op.addImage(source);
        op.addImage(dest);
        getConvertCmd().run(op);
    }

    /**
     * 添加水印
     *
     * @param source
     * @param dest
     * @param content
     * @throws Exception
     */
    public static void addText(String source, String dest, int x, int y, String content) throws Exception {
        IMOperation op = new IMOperation();
        op.pointsize(200).font("Arial").fill("#FFFFFF").draw(new StringBuffer("text ").append(x).append(", ").append(y).append(" '").append(content).append("'").toString());   //("x1 x2 x3 x4") x1 格式，x2 x轴距离 x3 y轴距离  x4名称    
        op.addImage();
        op.addImage();
        getConvertCmd().run(op, source, dest);
    }

    public static boolean isGif(String path) {
        InputStream is = null;
        try {
            is = new FileInputStream(path);
            byte[] buffer = new byte[8];
            is.read(buffer);
            String s = new String(buffer);
            if (s.contains("GIF8")) {
                return true;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return false;
    }

    /**
     * 根据传入宽和高 进行等比计算scale, 通过scale进行定位最大裁切crop x和y
     *
     * @param source
     * @param dest
     * @param width
     * @param height
     * @throws IOException
     * @throws InterruptedException
     * @throws IM4JavaException
     */
    public static void cropAndScale(String source, String dest, int width, int height, String sourceExtentName) throws IOException, InterruptedException, IM4JavaException {
        cropAndScale(source, dest, width, height, sourceExtentName, null);
    }

    /**
     * 根据传入宽和高 进行等比计算scale, 通过scale进行定位最大裁切crop x和y
     *
     * @param source
     * @param dest
     * @param width
     * @param height
     * @param quality
     * @throws IOException
     * @throws InterruptedException
     * @throws IM4JavaException
     */
    public static void cropAndScale(String source, String dest, int width, int height, String sourceExtentName, Double quality) throws IOException, InterruptedException, IM4JavaException {
        int srcWidth = 0, srcHeight = 0;
        int posX = 0, posY = 0;
        boolean go = true;
        try {
            double scale = width / (height * 1.0);//1.28;
            int srcSize[] = getSize(new File(source));
            srcWidth = srcSize[0];
            srcHeight = srcSize[1];
            posX = 0;
            posY = 0;

            double tmp = srcWidth / (srcHeight * 1.0);
            if (0.8 <= tmp && tmp <= scale) {
                //nothing
            } else {
                if (srcWidth < srcHeight) {
                    posY = (srcHeight - srcWidth) / 2;
                    srcHeight = srcWidth;
                } else if (srcWidth > srcHeight) {
                    posX = (srcWidth - srcHeight) / 2;
                    srcWidth = srcHeight;
                }
                int tmpScaleHeight = (int) (srcHeight / scale);
                posY += (srcHeight - tmpScaleHeight) / 2;
                srcHeight = tmpScaleHeight;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("error ! ", e);
            go = false;
        }

        IMOperation op = new IMOperation();
        op.addImage(source);
        if (go)
            op.crop(srcWidth, srcHeight, posX, posY);
        //op.resize(width, height);
        op.resize(width,height);
        op.resize(width,height,'!');
        //op.resize()
        if (quality != null && quality > 0) {
            op.quality(quality);
        }
        op.addImage(dest);

        getConvertCmd().run(op);
    }

    public static void zoomAndCut(String source, String dest, int width, int height, int x,int y,double zoom,String sourceExtentName)throws Exception{
        if (width == 0 || height == 0) {
            logger.error("width and height cannot be 0 !");
            return;
        }
        int srcSize[] = getSize(new File(source));

        IMOperation op = new IMOperation();
        op.addImage(source);
        op.resize((int)(srcSize[0]*zoom),(int)(srcSize[1]*zoom));
        op.crop(width, height, x, y);
        op.addImage(dest);

        getConvertCmd().run(op);
    }

    /**
     * 获取图片大小
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static int[] getSize(File file) throws Exception {
        //方法一：使用ImageMagick读图片信息
        IdentifyCmd identifyCmd = getIdentifyCmd();

        ArrayListOutputConsumer output = new ArrayListOutputConsumer();
        identifyCmd.setOutputConsumer(output);
        IMOperation op = new IMOperation();
        op.addImage(file.getAbsolutePath());
        identifyCmd.run(op);
        ArrayList<String> cmdOutput = output.getOutput();
        String width = cmdOutput.get(0).split(" ")[2].split("x")[0];
        String height = cmdOutput.get(0).split(" ")[2].split("x")[1];
        return new int[]{Integer.parseInt(width),Integer.parseInt(height)};

        //方法二 （方法三的精简版） 和三一样都会出现图片信息读取失败的情况
        /*BufferedImage bufImg =ImageIO.read(file);
        return new int[]{bufImg.getWidth(), bufImg.getHeight()};*/

        //方法三
        /*ImageInputStream iis = ImageIO.createImageInputStream(file);
        Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
        if (!readers.hasNext()) {
            throw new RuntimeException("No readers found!");
        }
        ImageReader reader = readers.next();
        reader.setInput(iis, true);
        int imageIndex = 0;
        int width = reader.getWidth(imageIndex);
        int height = reader.getHeight(imageIndex);
        iis.close();
        return new int[]{width, height};*/
    }

    /**
     *
     * 图片扁平化，可以将png透明背景转成白色
     * @param source
     * @param dest
     * @throws InterruptedException
     * @throws IOException
     * @throws IM4JavaException
     */
    public static void flatten(String source,String dest) throws InterruptedException, IOException, IM4JavaException {
        IMOperation op = new IMOperation();
        op.addImage(source);
        /*op.fill("#CCCCCC00");
        op.opaque("none");*/
        op.flatten();
        op.addImage(dest);
        getConvertCmd().run(op);
    }

    public static void flatten(String source,String dest,int width,int height) throws InterruptedException, IOException, IM4JavaException {
        IMOperation op = new IMOperation();
        op.addImage(source);
        op.flatten();
        op.resize(width,height);
        op.addImage(dest);
        getConvertCmd().run(op);
    }
}
